package co.yixiang.common.util;

import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * JwtToken类用于处理与JWT（JSON Web Token）相关的操作，包括生成、验证和解析JWT
 **/
@Component
public class JwtToken {

    // JWT密钥
    private static String jwtKey;
    // JWT过期时间（秒）
    private static Integer expiredTimeIn;
    // 默认权限范围
    private static Integer defaultScope = 8;

    /**
     * 设置JWT密钥
     * @param jwtKey JWT密钥
     */
    @Value("${yshop.security.jwt-key}")
    public void setJwtKey(String jwtKey) {
        JwtToken.jwtKey = jwtKey;
    }

    /**
     * 设置JWT过期时间
     * @param expiredTimeIn JWT过期时间（秒）
     */
    @Value("${yshop.security.token-expired-in}")
    public void setExpiredTimeIn(Integer expiredTimeIn) {
        JwtToken.expiredTimeIn = expiredTimeIn;
    }

    /**
     * 解析JWT并获取其中的声明
     * @param token JWT字符串
     * @return 如果JWT有效，则返回包含所有声明的Map；否则返回Optional.empty()
     */
    public static Optional<Map<String, Claim>> getClaims(String token) {
        DecodedJWT decodedJWT;
        Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            decodedJWT = jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            return Optional.empty();
        }
        return Optional.of(decodedJWT.getClaims());
    }

    /**
     * 验证JWT的有效性
     * @param token JWT字符串
     * @return 如果JWT有效，则返回true；否则返回false
     */
    public static Boolean verifyToken(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
        } catch (JWTVerificationException e) {
            return false;
        }
        return true;
    }

    /**
     * 获取JWT的过期时间
     * @param token JWT字符串
     * @return JWT的过期时间字符串
     */
    public static String getExpireTime(String token){
        return DateUtil.formatDateTime(JWT.decode(token).getExpiresAt());
    }

    /**
     * 生成包含指定权限范围的JWT
     * @param uid 用户ID
     * @param uName 用户名
     * @param scope 权限范围
     * @return 生成的JWT字符串
     */
    public static String makeToken(Long uid,String uName, Integer scope) {
        return JwtToken.getToken(uid,uName, scope);
    }

    /**
     * 生成包含默认权限范围的JWT
     * @param uid 用户ID
     * @param uName 用户名
     * @return 生成的JWT字符串
     */
    public static String makeToken(Long uid,String uName) {
        return JwtToken.getToken(uid,uName, JwtToken.defaultScope);
    }

    /**
     * 生成JWT
     * @param uid 用户ID
     * @param uName 用户名
     * @param scope 权限范围
     * @return 生成的JWT字符串
     */
    private static String getToken(Long uid,String uName, Integer scope) {
        Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
        Map<String,Date> map = JwtToken.calculateExpiredIssues();

        return JWT.create()
                .withClaim("uid", uid)
                .withClaim("scope", scope)
                .withClaim("uName", uName)
                .withExpiresAt(map.get("expiredTime"))
                .withIssuedAt(map.get("now"))
                .sign(algorithm);
    }

    /**
     * 计算JWT的过期时间和当前时间
     * @return 包含过期时间和当前时间的Map
     */
    private static Map<String, Date> calculateExpiredIssues() {
        Map<String, Date> map = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();
        calendar.add(Calendar.SECOND, JwtToken.expiredTimeIn);
        map.put("now", now);
        map.put("expiredTime", calendar.getTime());
        return map;
    }
}
